home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ShareWare OnLine 2
/
ShareWare OnLine Volume 2 (CMS Software)(1993).iso
/
prog
/
spx10.zip
/
SPX_DOC.ZIP
/
SPX_OBJ.DOC
< prev
next >
Wrap
Text File
|
1993-05-05
|
9KB
|
263 lines
{ SPX Library Version 1.0 Copyright 1993 Scott D. Ramsay }
SPX_OBJ is the object handling unit. It allows a easy way to
keep track of multiple objects. I'm assuming you know alittle about
Dynamic data structures with linked list and OOP. I don't know of
any good books I'd recommend. But I'm sure anything would be helpful.
"And in schooll I thought that I'd never use linked lists in real life. ;) "
Each object is a descendent of TOBJS. All objects are added to a
double linked list for the dynamic creation of numerous objects. When
removing objects from the list, we add the node to a 'kill' list which
we can quickly deallocate multiple objects.
Plist: Is our double linked pointer type which its data points to a TOBJS
Type
Pobjs = ^Tobjs;
Plist = ^Tlist;
Tlist = record
item : pobjs;
prev,next : plist;
end;
Here is the basic structure of the linked lists. Brackets [] specifies
actual records or objects.
var
head,tail : Plist; { Head/Tail pointers to our object list }
kill : Pkill; { Our kill list }
|- Tail
\|/
Head --> [Node1] <--> [Node2] <--> [Node3] <--> [Node4] --> NIL
| | | |
[Tobj] [Tobj] [Tobj] [Tobj]
Kill --> [Knode1] --> [Knode2] --> NIL
| |
\|/ \|/
[Node2] [Node4]
In the above example we have four objects in our list. With the
second and third node in the kill list (ready to be deleted).
That's basically the structure. To do calcuations on each object, we
just traverse the double linked list. Lets say that the object at Node2
was a space alien and was shot. Ok its dead, so we add it to the kill list.
After one iteration, usually the Kill list is traversed deallocating each
Node(n) from our double linked list.
pkill = ^tkill;
tkill = record
tk : plist; { TK - plist pointer To Kill }
next : pkill;
end;
───────────────────────────────────────────────────────────────────────────
Type
TObjs = object;
Generic object type. TObjs is the base for all objects that
need to be handled.
VARIABLES:
powner:plist A pointer to the object's node in the linked list;
killed:boolean TRUE if the object was added to a kill list;
cankill:boolean Set to TRUE if allowing the object to be added to
the kill list. (See checkhit for better descript);
overshow:boolean In my games I traverse the list twice. The first
time is to display the objects that will be behind
my character, the second time is for the objects
that are above my character. Set OVERSHOW to
TRUE for the object to be an over character.
(In the game RSQUID, the cloud objects are set
to TRUE "Always in front", all other objects are
set to FALSE. "Behind my main character";
id:integer For each object type I assign a unique number. This
is incase I need to find certain objects while
traversing the list
METHODS:
---------------------------------------------------
constructor Tobjs.init;
Sets up the object
DEFAULTS:
KILLED set to FALSE
ID set to 0
OVERSHOW set to TRUE
OVERRIDE: often
Here is how you add an object to the linked list;
var
p : plist;
begin
new(p); { Create a new node }
p^.item := new(Pobjs,init);{ Create the object }
p^.item^.powner := p; { IMPORTANT! have the object point to its node }
addp(head,tail,p); { Add the node to the list }
end;
See the procedure Add2Kill_list for reason for " p^.item^.powner := p;"
---------------------------------------------------
procedure TObjs.drawitemobject;
Displays the item.
OVERRIDE: often
Tobjs.drawitemobject is an empty function. In your drawitemobject
function it will usually draw a sprite.
---------------------------------------------------
procedure TObjs.calcitemobject;
Does any calcuations to the object such as changing the object's
position.
OVERRIDE: often
---------------------------------------------------
function TObjs.checkhit(hx,hy:integer;var item:pobjs):boolean;
Return TRUE if hx,hy is in range of an object.
HX,HY: Location to check;
ITEM: Tobjs that it is in conflict with
OVERRIDE: often
For example:
function TMyObject.checkhit(hx,hy:integer;var item:pobjs):boolean;
begin
checkhit := (abs(hx-MyObjectX)<10) and (abs(hy-MyObjectY)<10);
end;
This is basically a collision detection function. For example,
Lets assume we have a Tbullet object (desendant of Tobjs) that wants
to check if it hit anyother objects in the list. In the procedure
Tbullet.calcitemobject we would traverse the linked list calling
the checkhit function for each object in the list. If the function
returns TRUE, then the object collided with the object.
procedure Tbullet.calcitemobject;
var
p : plist;
begin
p := head;
while p<>nil do
begin
{ Don't check for colliding bullets or dead objects }
if (p^.item^.id<>id_bullet) and not p^.item^.killed
then
if p^.item^.checkhit(bullet_x,bullet_y,@self)
then { we hit the object! }
p := p^.next;
end;
end;
---------------------------------------------------
destructor TObjs.done;
Deallocates the object;
OVERRIDE: sometimes
───────────────────────────────────────────────────────────────────────────
procedure addp(var nkbeg,nkend,p:plist);
Add a node to the linked list
NKBEG: Linked list Head pointer;
NKEND: Linked list Tail pointer;
P: Node to add to the list
───────────────────────────────────────────────────────────────────────────
procedure deletep(var nkbeg,nkend,p:plist);
Delete a note from the list and deallocate the object connected to it
NKBEG: Linked list Head pointer;
NKEND: Linked list Tail pointer;
P: Node to delete to the list
───────────────────────────────────────────────────────────────────────────
procedure calcitems(var nkbeg:plist);
Traverses a linked list calling the node's object's calcitemobject method
NKBEG: Linked list Head pointer
NOTE: Still calls method even if the KILLED flag it true.
───────────────────────────────────────────────────────────────────────────
procedure drawitems(var nkbeg:plist;over:boolean);
Traverses a linked list calling the node's object's drawitem object method
NKBEG: Linked list Head pointer
OVER: Set to TRUE to call only objects with OVERSHOW set to TRUE
Set to FALSE to call only objects with OVERSHOW set to FALSE
───────────────────────────────────────────────────────────────────────────
procedure add2kill_list(var kill:pkill;var i:plist);
Adds a node to the kill list and sets the object's KILLED flag to TRUE.
KILL: Kill list to add the node;
I: Node to add to the kill list
This procedure is usually called with in a object's calcitemobject or
checkhit methods. Since this is the case, you CAN'T deallocate a
object while still in the object's method. So by adding the node/object
to a kill list. One can remove the object later.
Each object has a pointer to its node (powner) that is passed to the
kill list.
Example:
function TMyObject.checkhit(hx,hy:integer;var item:pobjs):boolean;
begin
if (abs(hx-MyObjectX)<10) and (abs(hy-MyObjectY)<10)
then
begin
checkhit := true;
add2kill_list(kill,powner);
end
else checkhit := false;
end;
───────────────────────────────────────────────────────────────────────────
procedure cleankill_list(var kill:pkill;var nkbeg,nkend:plist);
Traverses the KILL list deallocating node that are in the kill and
linked list.
KILL: Kill list to cleanout;
NKBEG: Linked list Head pointer;
NKEND: Linked list Tail pointer
On return KILL=NIL
───────────────────────────────────────────────────────────────────────────
procedure clean_plist(var nkbeg,nkend:plist);
Traverse the LINKED list deallocating every node.
NKBEG: Linked list Head pointer;
NKEND: Linked list Tail pointer
On return nkbeg=NIL and nkend=NIL
───────────────────────────────────────────────────────────────────────────